import { PackageManagerTabs } from '@theme';
import { Stability } from '@components/ApiMeta.tsx';

# Preact

## 如何使用

Rspack 提供两种方案来支持 Preact：

- **使用 Rsbuild**：Rsbuild 提供对 React 开箱即用的支持，能够快速创建一个 Preact 项目，详见 [Rsbuild - Preact](https://rsbuild.rs/zh/guide/framework/preact)。
- **手动配置 Rspack**：你可以参考当前文档，手动添加 Preact 相关的配置。

## 配置 JSX/TSX

Rspack 使用 SWC 转译器支持 JSX/TSX。

添加 `builtin:swc-loader` 以支持 `jsx` 和 `tsx`:

```js title="rspack.config.mjs"
export default {
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: {
          loader: 'builtin:swc-loader',
          options: {
            jsc: {
              parser: {
                syntax: 'ecmascript',
                jsx: true,
              },
            },
          },
        },
        type: 'javascript/auto',
      },
      {
        test: /\.tsx$/,
        use: {
          loader: 'builtin:swc-loader',
          options: {
            jsc: {
              parser: {
                syntax: 'typescript',
                tsx: true,
              },
            },
          },
        },
        type: 'javascript/auto',
      },
    ],
  },
};
```

关于配置项的更多信息请参考 [内置 swc-loader](/guide/features/builtin-swc-loader)。

完整示例可参考：[examples/preact](https://github.com/rspack-contrib/rstack-examples/blob/main/rspack/preact)

## Preact Refresh

需要开启 Preact Refresh 需要如下步骤：

- 添加 `@rspack/plugin-preact-refresh` 插件
- 添加代码转换相关 loader

### @rspack/plugin-preact-refresh

首先需要安装相关依赖：

<PackageManagerTabs command="add @rspack/plugin-preact-refresh @prefresh/core @prefresh/utils -D" />

[Preact Refresh](https://github.com/preactjs/prefresh) 功能的开启主要分为两部分：代码注入和代码转换：

- 代码注入：指注入与 `@prefresh/core` 和 `@prefresh/utils` 交互的代码，都已集成在 [@rspack/plugin-preact-refresh](https://github.com/rspack-contrib/rspack-plugin-preact-refresh) 插件中，可通过该插件实现
- 代码转换需要通过 loader 来完成：
  - 使用 `builtin:swc-loader` 或 [`swc-loader`](https://swc.rs/docs/usage/swc-loader)
    - 开启 `jsc.transform.react.refresh` 以支持通用的 react 转换
    - 在 `jsc.experimental.plugins` 中添加 [`@swc/plugin-prefresh`](https://github.com/swc-project/plugins/tree/main/packages/prefresh) 以支持 preact 特有的转换
  - 使用 `babel-loader` 并接入 prefresh 官方[babel 插件](https://github.com/preactjs/prefresh/tree/main/packages/babel)。

:::warning
在 1.0.0 以下版本, Rspack 不支持在 `swc-loader` 中使用 preact 特有转换。

请使用 `builtin:swc-loader` 并在配置中添加 `rspackExperiments.preact: {}` 以开启 preact 特有转换。
:::

```js title="rspack.config.mjs"
import PreactRefreshPlugin from '@rspack/plugin-preact-refresh';

const isDev = process.env.NODE_ENV === 'development';

export default {
  // ...
  mode: isDev ? 'development' : 'production',
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: {
          loader: 'builtin:swc-loader',
          options: {
            jsc: {
              experimental: {
                plugins: [
                  [
                    '@swc/plugin-prefresh', // 开启 preact 特有转换
                    {
                      library: ['preact-like-framework'], // 自定义的 preact 库名, 默认值为 `["preact", "preact/compat", "react"]`
                    },
                  ],
                ],
              },
              parser: {
                syntax: 'ecmascript',
                jsx: true,
              },
              transform: {
                react: {
                  development: isDev,
                  refresh: isDev, // 开启 react 通用转换
                },
              },
            },
          },
        },
      },
    ],
  },
  plugins: [
    isDev && new PreactRefreshPlugin(),
    isDev && new rspack.HotModuleReplacementPlugin(),
  ],
};
```

完整示例可参考：[examples/preact-refresh](https://github.com/rspack-contrib/rstack-examples/blob/main/rspack/preact-refresh)
